package cheme.Interpreter.AST.Arithmetic;

import cheme.Interpreter.AST.Interfaces.IAstType;
import cheme.Interpreter.AST.Interfaces.IAstValue;
import cheme.Interpreter.AST.Interfaces.IObserver;
import cheme.Interpreter.AST.Interfaces.ISubject;
import cheme.Interpreter.AST.Interfaces.SubjectCore;

public class AstValue implements IAstValue
{
	private double value = 0.0;
	private ValueationState valueationState = ValueationState.Unknown;
	
	private SubjectCore subjectCore = new SubjectCore(this);

	public AstValue()
	{
		valueationState = ValueationState.Unknown;
	}
	
	public AstValue(double value)
	{
		super();
		this.value = value;
		valueationState = ValueationState.Evaluated;
	}
	
	@Override
	protected Object clone() throws CloneNotSupportedException
	{
		AstValue clone = new AstValue();
		
		clone.value = value;
		clone.valueationState = valueationState;
		clone.subjectCore = (SubjectCore)subjectCore.clone();
		
		return clone;
	}

	public void setValue(double value)
	{
		this.value = value;
	}

	public double evaluate()
	{
		return value;
	}
	
	@Override
	public String toString()
	{
		if(ValueationState.Unknown == valueationState)
		{
			return "?";
		}
		
		return Double.toString(value);
	}
	
	@Override
	public boolean equals(Object arg0)
	{
		assert arg0 instanceof AstValue;
		return value == ((AstValue)arg0).value;
	}

	/*
	 * (non-Javadoc)
	 * @see edu.wsu.cheme.ChemeVM.AST.Interfaces.IAstExpression#isUnknown()
	 * 
	 * A value will always be known.
	 */
	public boolean isUnknown()
	{
		return ValueationState.Unknown == valueationState;
	}

	public void notify(ISubject s)
	{
		notifyObservers();
	}
	
	public void attach(IObserver o)
	{
		subjectCore.attach(o);
	}

	public void detach(IObserver o)
	{
		subjectCore.detach(o);
	}

	public void notifyObservers()
	{
		subjectCore.notifyObservers();
	}

	public ValueationState getValueationState()
	{
		return valueationState;
	}

	public IAstType getType()
	{
		return IAstType.nullType;
	}
}
